﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MLMBonus.Engine
{
    /// <summary>
    /// INode is used by the bonus engine to represent a node in the bonus genealogy. It is important that the engine
    /// receive an INode object with Id and ParentId populated correctly. It is also important to note that Id must
    /// be unique in the collection of nodes sent to the MLMBonus engine.
    /// </summary>
    public interface INode
    {
        #region Properties
        /// <summary>
        /// A unique Id for the INode object. Used to identify the object in any INode collection used.
        /// </summary>
        string Id { get; set; }
        /// <summary>
        /// The Id of the parent object, if any. This value should be null for the root INode.
        /// </summary>
        string ParentId { get; set; }
        /// <summary>
        /// If the node has already been preprocessed, this property will be set true. This property is reset to false
        /// at the beginning of a run.
        /// </summary>
        bool IsPreProcessed { get; set; }
        /// <summary>
        /// This property is set by the bonus engine as it walks the tree so that it can return to the parent once 
        /// it has finished processing
        /// </summary>
        LinkedListNode<INode> ParentNode { get; set; }
        /// <summary>
        /// This property will be set by the engine if the INode collection is sent in the BonusManager constructor.
        /// It is not used by the engine itself, but can be used by a bonus module to set parent properties as needed.
        /// </summary>
        INode Parent { get; set; }
        /// <summary>
        /// This LinkedList is populated when an INode collection is sent in the BonusManager constructor. It is vital
        /// that it is populated correctly for the bonus engine to be able to walk the genealogy.
        /// </summary>
        LinkedList<INode> Children { get; set; }
        /// <summary>
        /// Each IVolume will have its Pay method called during the INode's Pay phase. Bonus modules will use this to
        /// initiate bonus payouts.
        /// </summary>
        List<IVolume> Volumes { get; set; }
        /// <summary>
        /// This is dependency that should include pay and promote methods that will store payment and promotion information.
        /// </summary>
        IBonusContext Context { get; set; }
        #endregion
        #region Methods
        /// <summary>
        /// PreProcess will be called as the engine walks the genealogy down. This will be the first that the bonus
        /// will hit each INode and can be used to initialize important values such as commissionable and qualifying 
        /// volumes.
        /// </summary>
        /// <param name="BonusRunType">
        /// BonusRunType is used so that multiple run types can be handled by a single bonus module. It is expected that
        /// BonusRunType be used inside the method to determine the correct logic to be run at a given time.
        /// </param>
        void PreProcess(string BonusRunType);
        /// <summary>
        /// Promote is the first method called as the bonus engine ascends the genealogy after reaching a leaf node.
        /// </summary>
        /// <param name="BonusRunType">
        /// BonusRunType is used so that multiple run types can be handled by a single bonus module. It is expected that
        /// BonusRunType be used inside the method to determine the correct logic to be run at a given time.
        /// </param>
        void Promote(string BonusRunType);
        /// <summary>
        /// Pay is the second method called as the bonus engine ascends the genealogy. It is called after Promote so that
        /// the engine can take promotions into account if needed.
        /// </summary>
        /// <param name="BonusRunType">
        /// BonusRunType is used so that multiple run types can be handled by a single bonus module. It is expected that
        /// BonusRunType be used inside the method to determine the correct logic to be run at a given time.
        /// </param>
        void Pay(string BonusRunType);
        /// <summary>
        /// This is the final method called on each INode before the bonus engine moves on to a sibling or parent. 
        /// It should be used to clean up any processing or kick off important final events.
        /// </summary>
        /// <param name="BonusRunType">
        /// BonusRunType is used so that multiple run types can be handled by a single bonus module. It is expected that
        /// BonusRunType be used inside the method to determine the correct logic to be run at a given time.
        /// </param>
        void PostProcess(string BonusRunType);
        #endregion
    }
}
